package bd;

import java.io.IOException;
import java.io.ObjectOutputStream;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.LinkedList;

import Cliente.interface_grafico.DatasDeNascimento;
import Cliente.interface_grafico.DatasDeRegisto;

import mensagem.MIdJogador;
import mensagem.MListaJogadores;
import mensagem.MObjectArray;
import mensagem.MProcuraJogador;
import mensagem.MSimples;
import mensagem.MSubmeterPerfil;
import mensagem.MVerEstatistica;
import mensagem.MVerPerfil;
import mensagem.TipoMensagem;

public class BD implements Runnable {

	private ObjectOutputStream out;
	private MSimples mensagem;
	private BDConnection conexao_bd;

	public BD(ObjectOutputStream out, MSimples mensagem, BDConnection bd) {
		super();
		assert (out != null && mensagem != null);
		this.out = out;
		this.mensagem = mensagem;

		//Iniciar a base de dados.
		try {
			this.conexao_bd = bd;
		} catch (Exception e) {
			try {
				synchronized(out){
					out.writeObject(new MSimples(TipoMensagem.BD_ERRO));
					out.flush();
				}
			} catch (IOException ioe) {
				e.printStackTrace();
			}
		}
	}


	@Override
	public void run() {
		if(mensagem.getTipo() == TipoMensagem.CLIENTE_VERPERFIL){
			System.out.println("Cliente quer ver Perfil");
			//O cliente deseja ver o Perfil dele (os dados guardados sobre ele).
			ResultSet result_set=null;
			ResultSet result_paises = null;
			try {
				synchronized(conexao_bd){
					result_set = conexao_bd.executeQuery("CALL PERFIL(" + ((MIdJogador)mensagem).getId() + ");");
				}
				if(result_set.next()){
					char sexo = 'x';
					if (result_set.getString(5) != null){
						sexo = result_set.getString(5).charAt(0);
					}
					//LER PAISES
					LinkedList<String> resultado = null;
					try {
						result_paises = conexao_bd.executeQuery("SELECT * FROM nacionalidade");
					resultado = new LinkedList<String>();
					while(result_paises.next()){
						resultado.add(result_paises.getString(1));
					}
					} catch (SQLException e) {}
					
					String[] paises_final = resultado.toArray(new String[1]);

					MVerPerfil resposta = new MVerPerfil(TipoMensagem.SERVIDOR_PERFIL, result_set.getInt(1), result_set.getString(2), result_set.getString(3), result_set.getString(4), sexo, result_set.getString(6), result_set.getString(7),paises_final);
					synchronized(out){
						try {
							out.writeObject(resposta);
							out.flush();
						} catch (IOException e) {
							try {
								out.writeObject(new MSimples(TipoMensagem.MENSAGEM_ERRO));
								out.flush();
							} catch (IOException ioe) {
								e.printStackTrace();
							}
						}
					}
				}else{
					try {
						out.writeObject(new MSimples(TipoMensagem.MENSAGEM_ERRO));
						out.flush();
					} catch (IOException ioe) {
						ioe.printStackTrace();
					}
				}

			} catch (SQLException e) {
				try {
					synchronized(out){
						out.writeObject(new MSimples(TipoMensagem.BD_ERRO));
						out.flush();
					}
				} catch (IOException ioe) {
					e.printStackTrace();
				}
			}

		}else if(mensagem.getTipo() == TipoMensagem.CLIENTE_SUBMETERPERFIL){
			//O cliente deseja submeter informa??o no Perfil.
			MSubmeterPerfil m_subm_perfil = (MSubmeterPerfil)mensagem;
			System.out.println("ENTREI NO CLIENTE SUBMETER PERFIL");
			try {
				String password_novo = m_subm_perfil.getPassword_novo();
				if(password_novo.equals("")){
					password_novo = "null";
				}else{
					password_novo = "'" + password_novo + "'";
				}

				String password_antigo = m_subm_perfil.getPassword_antigo();
				if(password_antigo.equals("")){
					password_antigo = "null";
				}else{
					password_antigo = "'" + password_antigo + "'";
				}

				String pais = m_subm_perfil.getPais();
				if(pais == null || pais.equals("")){
					pais = "null";
				}else{
					pais = "'" + pais + "'";
				}

				String data_nascimento = m_subm_perfil.getData_nascimento();
				if(data_nascimento.equals("")){
					data_nascimento = "null";
				}else{
					data_nascimento = "'"+ m_subm_perfil.getData_nascimento()+"'";
				}
				synchronized(conexao_bd){
					conexao_bd.execute("CALL UPDATE_PERFIL(" + m_subm_perfil.getId() + ", '" + m_subm_perfil.getNick() + "', '" + m_subm_perfil.getNome() + "', " + password_antigo + ", " + password_novo + ", '" + m_subm_perfil.getEmail() + "', " + pais + ", '" + m_subm_perfil.getSexo() + "', " + data_nascimento + ");");
				}
				try{
					MSimples resposta = new MSimples(TipoMensagem.BD_OK);
					synchronized(out){
						out.writeObject(resposta);
						out.flush();
					}
				}catch(IOException ioe){
					ioe.printStackTrace();
				}
			} catch (SQLException e) {
				try {
					synchronized(out){
						out.writeObject(new MSimples(TipoMensagem.BD_ERRO));
						out.flush();
					}
				} catch (IOException ioe) {
					e.printStackTrace();
				}
			}
		}else if(mensagem.getTipo() == TipoMensagem.CLIENTE_PESQUISA){
			ResultSet rs = null;
			LinkedList<String> resultado = null;
			try {
				rs = conexao_bd.executeQuery("SELECT * FROM nacionalidade");
			resultado = new LinkedList<String>();
			while(rs.next()){
				resultado.add(rs.getString(1));
			}
			} catch (SQLException e) {}
			resultado.addFirst("");
			MObjectArray<String> resposta = new MObjectArray<String>(TipoMensagem.SERVIDOR_PESQUISA, resultado.toArray(new String[1]));
			
				try {
					synchronized(out){
					out.writeObject(resposta);
					out.flush();
					}
				} catch (IOException e) {} 
				
		}else if(mensagem.getTipo() == TipoMensagem.CLIENTE_VERESTATISTICA){
			//O cliente deseja ver as suas estatisticas.
			ResultSet result_set=null;
			try {
				synchronized(conexao_bd){
					result_set = conexao_bd.executeQuery("CALL ESTATISTICA(" + ((MIdJogador)mensagem).getId() + ");");
				}

				result_set.next();
				MVerEstatistica resposta = new MVerEstatistica(TipoMensagem.SERVIDOR_ESTATISTICA, result_set.getInt(1), result_set.getString(2), result_set.getInt(3), result_set.getInt(4), result_set.getInt(5), result_set.getString(6), result_set.getInt(7), result_set.getInt(8), result_set.getInt(9));
				synchronized(out){
					try {
						out.writeObject(resposta);
						out.flush();
					} catch (IOException e) {
						try {
							out.writeObject(new MSimples(TipoMensagem.MENSAGEM_ERRO));
							out.flush();
						} catch (IOException ioe) {
							e.printStackTrace();
						}
					}
				}

			} catch (SQLException e) {
				try {
					synchronized(out){
						out.writeObject(new MSimples(TipoMensagem.BD_ERRO));
						out.flush();
					}
				} catch (IOException ioe) {
					e.printStackTrace();
				}
			}
		}else if(mensagem.getTipo() == TipoMensagem.CLIENTE_TOP){
			//O cliente deseja ver a classificacao dos melhores jogadores.

			ResultSet result_set=null;
			try {
				synchronized(conexao_bd){
					result_set = conexao_bd.executeQuery("CALL TOP_JOGADORES(10);");
				}

				MListaJogadores resposta = new MListaJogadores(TipoMensagem.SERVIDOR_TOP);
				while(result_set.next()){
					int id = result_set.getInt(1);
					String nick = result_set.getString(2);
					String nome = result_set.getString(3);

					char sexo = 'x';
					if (result_set.getString(4) != null){
						sexo = result_set.getString(4).charAt(0);
					}
					
					int pontos = result_set.getInt(6);
					resposta.add(id, nick, nome, sexo, result_set.getString(5), pontos);
				}
				synchronized(out){
					try {
						out.writeObject(resposta);
						out.flush();
					} catch (IOException e) {
						try {
							out.writeObject(new MSimples(TipoMensagem.MENSAGEM_ERRO));
							out.flush();
						} catch (IOException ioe) {
							e.printStackTrace();
						}
					}
				}

			} catch (SQLException e) {
				try {
					synchronized(out){
						out.writeObject(new MSimples(TipoMensagem.BD_ERRO));
						out.flush();
					}
				} catch (IOException ioe) {
					e.printStackTrace();
				}
			}
		}else if(mensagem.getTipo() == TipoMensagem.CLIENTE_PROCURA_JOGADOR){
			//O jogador pesquisa por um outro jogador.
			MProcuraJogador procura = (MProcuraJogador)mensagem;

			//Preparacao dos argumentos de pesquisa.
			String pesquisa = "";

			if(procura.getId() != -1){
				pesquisa += "AND id_jogador = " + procura.getId() + " ";
			}
			
			if(procura.getSexo() == 'm'){
				pesquisa += "AND (sexo = 'm') ";
			}else if(procura.getSexo() == 'f'){
				pesquisa += "AND (sexo = 'f') ";
			}
			
				pesquisa += "AND nick LIKE '%" + procura.getNick() + "%' ";
				pesquisa += "AND nome LIKE '%" + procura.getNome() + "%' ";
				pesquisa += "AND email LIKE '%" + procura.getEmail() + "%' ";
			
			if(procura.getData_nascimento().equals(DatasDeNascimento.CRIANCA.toString())){
				pesquisa+= "AND data_nascimento BETWEEN today()-(365*12)AND today()";
			}else if(procura.getData_nascimento().equals(DatasDeNascimento.JOVEM.toString())){
				pesquisa+= "AND data_nascimento BETWEEN today()-(365*29)AND today()-(365*13)";
			}else if(procura.getData_nascimento().equals(DatasDeNascimento.ADULTO.toString())){
				pesquisa+= "AND data_nascimento BETWEEN today()-(365*45)AND today()-(365*30)";
			}else if(procura.getData_nascimento().equals(DatasDeNascimento.SENIOR.toString())){
				pesquisa+= "AND data_nascimento BETWEEN today()-(365*200)AND today()-(365*46)";
			}
			

			if(procura.getDesconexoes() == -1){
				pesquisa += "AND (desconexoes >= 0 OR desconexoes < 0) ";
			}else{
				pesquisa += "AND desconexoes = " + procura.getDesconexoes() + " ";
			}

			if(procura.getNr_jogos_ranking() == -1){
				pesquisa += "AND (nr_jogos_ranking >= 0 OR nr_jogos_ranking < 0) ";
			}else{
				pesquisa += "AND nr_jogos_ranking = " + procura.getNr_jogos_ranking() + " ";
			}

			if(procura.getNr_jogos_amigaveis() == -1){
				pesquisa += "AND (nr_jogos_amigaveis >= 0 OR nr_jogos_amigaveis < 0) ";
			}else{
				pesquisa += "AND nr_jogos_amigaveis = " + procura.getNr_jogos_amigaveis() + " ";
			}

			//Dependendo da data de registo(Qualquer,ontem,semana,mes,ano) a pesquisa terá parametros diferentes
			if(procura.getData_registo().equals(DatasDeRegisto.ONTEM.toString())){
				pesquisa+="AND data_de_registo Between today()-1 and today()";
			}else if(procura.getData_registo().equals(DatasDeRegisto.ULTIMA_SEMANA.toString())){
				pesquisa+="AND data_de_registo Between today()-7 and today()";
			}else if(procura.getData_registo().equals(DatasDeRegisto.ULTIMO_MES.toString())){
				pesquisa+="AND data_de_registo Between today()-31 and today()";
			}else if(procura.getData_registo().equals(DatasDeRegisto.ULTIMO_ANO.toString())){
				pesquisa+="AND data_de_registo Between today()-365 and today()";
			}

			if(procura.getNr_vitorias_ranking() == -1){
				pesquisa += "AND (nr_vitorias_ranking >= 0 OR nr_vitorias_ranking < 0) ";
			}else{
				pesquisa += "AND nr_vitorias_ranking = " + procura.getNr_vitorias_ranking() + " ";
			}

			if(procura.getNr_vitorias_amigaveis() == -1){
				pesquisa += "AND (nr_vitorias_amigaveis >= 0 OR nr_vitorias_amigaveis < 0) ";
			}else{
				pesquisa += "AND nr_vitorias_amigaveis = " + procura.getNr_vitorias_amigaveis() + " ";
			}

			if(procura.getRank_points() == -1){
				pesquisa += "AND (rank_points >= 0 OR rank_points < 0) ";
			}else{
				pesquisa += "AND rank_points = " + procura.getRank_points() + " ";
			} 
			if(procura.getPais()!=null && !procura.getPais().equals("")) {
				pesquisa += "AND pais = '"+procura.getPais()+"' ";
			}

			//Procura na base de dados.
			ResultSet result_set=null;
			try {
				synchronized(conexao_bd){
					System.out.println("############################## pesquisa: \r\n"+"SELECT id_jogador, nick, nome, sexo, pais, rank_points FROM JOGADOR WHERE activo = 1 " + pesquisa + ";");
					
					result_set = conexao_bd.executeQuery("SELECT id_jogador, nick, nome, sexo, pais, rank_points FROM JOGADOR WHERE activo = 1 " + pesquisa + ";");
				}

				MListaJogadores resposta = new MListaJogadores(TipoMensagem.SERVIDOR_PROCURA_JOGADOR);
				while(result_set.next()){
					int id = result_set.getInt(1);
					String nick = result_set.getString(2);
					String nome = result_set.getString(3);

					char sexo = 'x';
					if (result_set.getString(4) != null){
						sexo = result_set.getString(4).charAt(0);
					}
					
					int pontos = result_set.getInt(6);
					resposta.add(id, nick, nome, sexo, result_set.getString(5), pontos);
				}
				synchronized(out){
					try {
						out.writeObject(resposta);
						out.flush();
					} catch (IOException e) {
						try {
							out.writeObject(new MSimples(TipoMensagem.MENSAGEM_ERRO));
							out.flush();
						} catch (IOException ioe) {
							e.printStackTrace();
						}
					}
				}

			} catch (SQLException e) {
				e.printStackTrace();
				try {
					synchronized(out){
						out.writeObject(new MSimples(TipoMensagem.BD_ERRO));
						out.flush();
					}
				} catch (IOException ioe) {
					e.printStackTrace();
				}
			}
		}else{
			try {
				synchronized(out){
					out.writeObject(new MSimples(TipoMensagem.MENSAGEM_ERRO));
					out.flush();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}

